home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_11_12 / winroth / xception.h < prev   
Encoding:
C/C++ Source or Header  |  1993-10-20  |  9.8 KB  |  297 lines

  1. /*
  2. ** Exception Library -- General exception handling for ANSI C programs
  3. ** 
  4. ** Copyright (C) 1992 Computational Vision and Active Perception Lab. (CVAP),
  5. **                    Royal Institute of Technology, Stockholm.
  6. **
  7. ** This library is free software; you can redistribute it and/or
  8. ** modify it under the terms of the GNU Library General Public
  9. ** License as published by the Free Software Foundation; either
  10. ** version 2 of the License, or (at your option) any later version.
  11. ** 
  12. ** This library is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. ** Library General Public License for more details.
  16. ** 
  17. ** You should have received a copy of the GNU Library General Public
  18. ** License along with this library (see COPYING-LIB); if not, write to 
  19. ** the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 
  20. ** USA.
  21. ** 
  22. **                            Written by
  23. **
  24. **                   Harald Winroth, Matti Rendahl
  25. **         Computational Vision and Active Perception Laboratory
  26. **            Royal Institute of Technology
  27. **              S-100 44 Stockholm
  28. **                Sweden
  29. **
  30. ** Report bugs to candela-bug@bion.kth.se, and direct all inquiries to 
  31. ** candela@bion.kth.se.
  32. **
  33. */
  34.  
  35. #ifndef EXCEPTION_EXCEPTION_H
  36. #define EXCEPTION_EXCEPTION_H
  37.  
  38. #include <setjmp.h>
  39. #include <stdarg.h>
  40.  
  41. #include <exception/config.h>
  42.  
  43. typedef enum 
  44.     excNoCallback           = 0x0,
  45.  
  46.     excBeginCallback        = 0x1, 
  47.     excEndCallback          = 0x2, 
  48.     excThrowCallback        = 0x4,
  49.     excRecoverCallback      = 0x8,
  50.  
  51.     excCompleteCallback     = excBeginCallback    | \
  52.                           excEndCallback      | \
  53.                   excThrowCallback    | \
  54.                   excRecoverCallback
  55. } excCallbackTag;
  56.  
  57. typedef struct _excBuf 
  58. {
  59.     volatile struct _excBuf *prev, *prev_dynamic;
  60.     unsigned int level;
  61.     unsigned int cb_list_len; 
  62.     unsigned int try_data_sp;
  63.     int in_unwind; /* True if longjmp has been taken */
  64.     jmp_buf buf;
  65.     void *local_try_data[EXC_LOCAL_TRY_DATA_SIZE];
  66.  
  67. } excBuf;
  68.  
  69. typedef void (*excCallback) (excCallbackTag tag, void *cb_data, 
  70.                  void **try_data);
  71. typedef int (*excHandler) (void *e, void *e_type, void *h_data);
  72.  
  73. /* 
  74.  * Place holders (to generate unique addresses) 
  75.  */
  76.  
  77. extern int exc_any; /* Can be used with EXC_INSTALL_HANDLER() */
  78. extern int exc_undefined;
  79.  
  80. #define EXC_ANY (&exc_any)
  81. #define EXC_UNDEFINED (&exc_undefined)
  82.  
  83. /*
  84.  * Functions for manipulating the signal mask saved at the throw-point.
  85.  * If and when the program recovers from the pending exception, this mask
  86.  * will be restored. These functions are equivalent to the SYSV sigsetops(3)
  87.  * but the signal set argument (sigset_t*) is implicit.
  88.  */
  89.  
  90. extern int exc_sigemptyset (void);
  91. extern int exc_sigfillset (void);
  92. extern int exc_sigaddset (int signo);
  93. extern int exc_sigdelset (int signo);
  94. extern int exc_sigismember (int signo);
  95.  
  96. /*
  97.  * Exported functions
  98.  */
  99.  
  100. extern void exc_breakpoint (void); /* Set breakpoints in this dummy function */
  101.  
  102. extern void exc_throw_typed (void *e, void *e_type);
  103. extern void exc_throw (void *e);
  104. extern void exc_rethrow ();
  105.  
  106. extern void *exc_exception (void);
  107. extern void *exc_type (void);
  108.  
  109. extern int exc_in_domain (void *e, void *domain, unsigned long sizeof_domain);
  110. extern int exc_equal (void *e1, void *e2);
  111.  
  112. extern void exc_install_callback (excCallbackTag tags, excCallback cb,
  113.                   void *cb_data);
  114. extern void exc_remove_callback (excCallbackTag tags, excCallback cb,
  115.                  void *cb_data);
  116.  
  117. extern void exc_install_handler (void *e, unsigned long e_size, 
  118.                  excHandler h, void *h_data);
  119. extern void exc_remove_handler (void *e, unsigned long e_size, excHandler h, 
  120.                 void *h_data);
  121.  
  122.  
  123. /*
  124.  * Private -- don't use these in application programs
  125.  */
  126.  
  127. extern volatile excBuf *exc_current_buf;
  128.  
  129. extern volatile excBuf exc_buf;  /* Dummy */
  130. extern char exc_in_try;          /* Dummy */
  131. extern char exc_in_tret;         /* Dummy */
  132. extern char exc_in_unwind;       /* Dummy */
  133. extern char exception;           /* Dummy */
  134.  
  135. extern void *exc_malloc (unsigned long size);
  136. extern void *exc_calloc (unsigned long count, unsigned long size);
  137. extern void *exc_realloc (void *s, unsigned long size);
  138. extern void exc_free (void *s);
  139. extern char *exc_strdup (char *s);
  140.  
  141. extern void exc_vfatal (char *format, va_list list);
  142. extern void exc_fatal (char *format, ...);
  143. extern void exc_panic (void);
  144. extern void exc_assertion_failed (char *file, int line);
  145.  
  146. #define EXC_ASSERT(condition) \
  147.     if (!(condition)) exc_assertion_failed (__FILE__, __LINE__);
  148.  
  149. extern void exc_begin (volatile excBuf *buf, int inside_try);
  150. extern void exc_end (volatile excBuf *buf);
  151. extern int exc_tret (volatile excBuf *buf, int in_tret, char *file, int line);
  152.  
  153. extern void exc_break_in_try_err (char *file, int line);
  154. extern void exc_rethrow_err (char *file, int line);
  155. extern int exc_catch_outside_unwind_err (char *file, int line);
  156. extern void exc_ret_in_try_err (char *file, int line);
  157. extern int exc_tret_err (char *file, int line);
  158.  
  159. #if 0 /* Run-time overhead */
  160. #define EXC_IN_TRY (exc_in_try) 
  161. #define EXC_IN_TRET (exc_in_tret)
  162. #define EXC_IN_UNWIND (exc_in_unwind)
  163. #else
  164. #define EXC_IN_TRY (sizeof (exc_in_try) > 1)
  165. #define EXC_IN_TRET (sizeof (exc_in_tret) > 1)
  166. #define EXC_IN_UNWIND (sizeof (exc_in_unwind) > 1)
  167. #endif
  168.  
  169. #define return switch (EXC_IN_TRY ?                            \
  170.     exc_tret (&exc_buf, EXC_IN_TRET, __FILE__, __LINE__) : 0)                 \
  171.     default: return 
  172.  
  173. /*
  174.   Note: In tryreturn() below, the argument 'X' must be an lvalue. 
  175.         The (0 ? &(X) : 0) expression returns a NULL pointer of X's type.
  176.     The ((char *) &(X)) expression evaluates 'X' in the current TRY 
  177.     scope, which is important if 'X' contains an expression that might
  178.     throw an exception, such as 'idx()' in 'array[idx()]'.
  179. */
  180.  
  181. #define tryreturn(X) /* Note: X must be a lvalue */                  \
  182.     do {                                      \
  183.         long exc_in_tret = EXC_IN_TRY ? 1 : exc_tret_err (__FILE__, __LINE__);\
  184.         char *exc_tret_tmp = (char *) &(X);                      \
  185.         return (0 ? &(X) : 0)                              \
  186.             [(exc_tret_tmp-(char *)0)/sizeof(X)];                  \
  187.     } while(0)
  188.  
  189. #define TRY(TRYFORMS, CATCHFORMS)                          \
  190.     do {                                      \
  191.         volatile excBuf exc_buf;                          \
  192.         exc_begin (&exc_buf, EXC_IN_TRY);                      \
  193.         {                                      \
  194.         long exc_in_try = 1;                          \
  195.                                           \
  196.         if (EXC_SETJMP (exc_buf.buf) == 0)                              \
  197.         {                                      \
  198.         exc_current_buf = &exc_buf;                      \
  199.                                           \
  200.         do {                                  \
  201.             switch (0) { default: { TRYFORMS ; } continue; }          \
  202.             exc_break_in_try_err (__FILE__, __LINE__);              \
  203.             exc_in_try++; /* Not reached */                  \
  204.         } while (0);                              \
  205.                                           \
  206.         exc_end (&exc_buf);                          \
  207.         }                                      \
  208.         else {                                  \
  209.         do {                                  \
  210.             void *exception = exc_exception ();                  \
  211.             long exc_in_unwind = 1;                      \
  212.                                               \
  213.             switch (0)                              \
  214.             {                                  \
  215.             default:                              \
  216.             EXC_ASSERT (exc_current_buf == &exc_buf);          \
  217.             { CATCHFORMS ; }                      \
  218.             THROW (exception);                      \
  219.             }                                  \
  220.             exc_break_in_try_err (__FILE__, __LINE__);              \
  221.         } while (0);                              \
  222.                                           \
  223.         exc_end (&exc_buf);                              \
  224.         }                                      \
  225.     }                                      \
  226.     } while (0)
  227.  
  228. #define EXC_IN_DOMAIN(EXCEPTION, DOMAIN)                      \
  229.     exc_in_domain ((EXCEPTION), & DOMAIN, sizeof (DOMAIN))
  230.  
  231. #define EXC_EQUAL(EXCEPTION, MEMBER)                          \
  232.     exc_equal ((EXCEPTION), & MEMBER)
  233.  
  234. #define CATCH(DOMAIN, FORMS)                              \
  235.     switch (EXC_IN_UNWIND ? EXC_IN_DOMAIN (exc_exception (), DOMAIN)           \
  236.         : exc_catch_outside_unwind_err (__FILE__, __LINE__))          \
  237.     {                                          \
  238.         case 0: break;                                  \
  239.     default: { FORMS ; } continue;                          \
  240.     }
  241.  
  242. #define THROW_TYPED(EXCEPTION, TYPE)                          \
  243.     if ((void *) & EXCEPTION == (void *) & exception)                  \
  244.     {                                          \
  245.         if (EXC_IN_UNWIND)                              \
  246.             exc_rethrow ();                              \
  247.         else                                      \
  248.             exc_rethrow_err (__FILE__, __LINE__);                  \
  249.     }                                          \
  250.     else                                      \
  251.         exc_throw_typed (& EXCEPTION, & TYPE)
  252.  
  253. #define THROW(EXCEPTION) THROW_TYPED (EXCEPTION, EXCEPTION)
  254.  
  255. #define RETHROW() THROW (exception) /* alternative syntax */
  256.  
  257. #define UNWIND_PROTECT(PROTECTEDFORMS, CLEANUPFORMS)                  \
  258.     do {                                      \
  259.     static int _unwind_protect;                          \
  260.                                           \
  261.     TRY (                                      \
  262.     {                                      \
  263.         { PROTECTEDFORMS ; }                          \
  264.         THROW (_unwind_protect);                          \
  265.         },                                      \
  266.     {                                      \
  267.         { CLEANUPFORMS ; }                              \
  268.         CATCH (_unwind_protect, continue);                      \
  269.     }                                      \
  270.          );                                      \
  271.     } while (0)
  272.  
  273. #define EXC_INSTALL_HANDLER(E, HANDLER, HANDLER_DATA)                  \
  274.     exc_install_handler (&E, sizeof (E), (HANDLER), (HANDLER_DATA))
  275.  
  276. #define EXC_REMOVE_HANDLER(E, HANDLER, HANDLER_DATA)                  \
  277.     exc_remove_handler (&E, sizeof (E), (HANDLER), (HANDLER_DATA))
  278.  
  279. /*
  280.  * Note: EXC_LONGJMP must NOT affect the curret signal mask. THROW blocks
  281.  * all signals, and the signals must remain blocked until all unwind code
  282.  * has been executed.
  283.  *
  284.  * The (jmp_buf *) cast is to avoid a type clash: buf is volatile.
  285.  */
  286.  
  287. #if defined(SVR4) || defined(SYSV) || defined(_SYSV_)
  288. #define EXC_SETJMP(buf) setjmp (*(jmp_buf *)&(buf))
  289. #define EXC_LONGJMP(buf, val) longjmp(*(jmp_buf *)&(buf), val)
  290. #else
  291. #define EXC_SETJMP(buf) _setjmp (*(jmp_buf *)&(buf))
  292. #define EXC_LONGJMP(buf, val) _longjmp(*(jmp_buf *)&(buf), val)
  293. #endif
  294.  
  295. #endif /* EXCEPTION_EXCEPTION_H */
  296.